/**
 * 
 */

package net.messagenet.mazor.web.mngbeans;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.faces.model.SelectItem;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import net.messagenet.mazor.DO.CustomerDO;
import net.messagenet.mazor.DO.DpaDO;
import net.messagenet.mazor.DO.DpaProductDO;
import net.messagenet.mazor.DO.PosDO;
import net.messagenet.mazor.DO.PosProductDO;
import net.messagenet.mazor.DO.ProductDO;
import net.messagenet.mazor.ejb.facade.MZRFacadeLocal;
import net.messagenet.mazor.exception.MZRApplicativeException;
import net.messagenet.mazor.exception.MZRInternalServerException;
import net.messagenet.mazor.infra.cache.UserCacheManager;

import org.ajax4jsf.model.KeepAlive;
import org.apache.log4j.Logger;
import org.hibernate.validator.Email;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Pattern;


@KeepAlive
public class NewPosManagedBean implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5388230760485952510L;
	private UserCacheManager cacheManager;
	private String selectedDpaIdFormTable;
	private int selectedProdFormTable;
	private List<DpaProductDO> productList;

	//	private UserCacheManager cacheManager;
	private MZRFacadeLocal facade=null;
	

	private Logger logger = Logger.getLogger(this.getClass());

	private HashMap<Integer, DpaProductDO> prodMap;

	@Email
    @NotEmpty
	private String email;
	@Pattern(regex="(\\w+@\\w+\\.\\w+)+(,\\w+@\\w+\\.\\w+)*", message="Not a valid CC field")
	private String cc;

	//Fields for the dpa panel
	private CustomerDO customer;
	private String userCountry;
	private int distiInvoice;
	private int distiLine;
	private ProductDO product;
	private String dpaId;
	private double sdc;
	private double dpaCost;
	private int qty;
	private int maxQty;
	private String transCurr ;
	private double distributorResalePrice;
	private Date shipDate;
	
	//Fields for the not dpa panel
	private CustomerDO customerN;
	private String userCountryN;
	private int distiInvoiceN;
	private int distiLineN;
	private ProductDO productN;
	private double sdcN;
	private int qtyN;
	private String transCurrN ;
	private double distributorResalePriceN;
	private Date shipDateN;
	

	private int removePrdIdx;
	private Map<String,DpaDO> dpaMap;

	private List<DpaDO> dpaList;
	private List<PosProductDO> posProductList;
	private List<PosDO> drafts;
	private List<SelectItem > draftsLabel;
	
	private String selectedDraft;
	private int posId;
	private int dpaProdId;
	private List<PosProductDO> removePrds;
	
	

	
	@PostConstruct
	public void init() throws MZRInternalServerException, MZRApplicativeException {
		
		InitialContext ic;
			
		try {
				ic = new InitialContext();
				facade = (MZRFacadeLocal) ic.lookup("MZRFacade/local");
			} catch (NamingException e) {
				logger.error(e.getMessage(),e);
			}
//			logger.debug("loadding cusomter cache");
			try {
				cacheManager = facade.getUserCacheManager();
			} catch (MZRInternalServerException e) {
				logger.error(e.getMessage(), e);
			}
			
			productList= new LinkedList<DpaProductDO>();
			dpaMap=facade.getAllApprovedDPAs();
			dpaList= new LinkedList<DpaDO>();
			Iterator<Entry<String, DpaDO>> it = dpaMap.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry<String, DpaDO> entry = (Map.Entry<String, DpaDO>) it
						.next();
				dpaList.add(entry.getValue());
			}
			
			posProductList = new LinkedList<PosProductDO>();
		//	productList=dpaList.get(0).getDpaProducts();
			
			customer = new CustomerDO();
			product= new ProductDO();
			customerN = new CustomerDO();
			productN = new ProductDO();
			
			
			
			logger.debug("getting drafts");
			drafts = facade.getPOSDrafts();
			draftsLabel = new LinkedList<SelectItem>();
			for (PosDO posDo : drafts) {
				draftsLabel.add(new SelectItem(String.valueOf(posDo.getFileName())));
			}
			
			removePrds = new LinkedList<PosProductDO>();
	
	   }
	/**
	 * This method is called by ajax from autocomplete
	 * 
	 * @param suggest prefix
	 * @return
	 */
    public List<CustomerDO> autoCompleteCustomer(Object suggest){
    	List<CustomerDO> result = cacheManager.getCustomersWithPrefix((String)suggest);
    	return result;
    }
	/**
	 * This method is called by ajax from autocomplete
	 * 
	 * @param suggest prefix
	 * @return
	 */
    public List<ProductDO> autoCompletePrd(Object suggest){
    	List<ProductDO> result = cacheManager.getProductsWithPrefix((String)suggest);
    	return result;
    }
    /**
     * This method is called when the user chose a dpa object from the dpa list.
     * this method updates the second table of the proudcts
     * 
     */
	public void selectDpaFromTable(){
		DpaDO dpaSelected=dpaMap.get(selectedDpaIdFormTable);
		productList=dpaSelected.getDpaProducts();
		//making a map of the products
		prodMap = new HashMap<Integer,DpaProductDO>();
		for (DpaProductDO p : productList) {
			prodMap.put(p.getProduct().getId(), p);
		}
	}
	/**
	 * This method is called when the user chose a proudct from the list.
	 * This method fills the fields of the products
	 * 
	 */
	public void selectProdFromTable(){
		
		DpaDO dpa =dpaMap.get(selectedDpaIdFormTable);
		DpaProductDO prd =prodMap.get(selectedProdFormTable);
		//filling the data
		if ((prd.getQuantity()-prd.getQuantityReported()) != 0){
			dpaId=dpa.getDpaId();
			qty= prd.getQuantity()-prd.getQuantityReported();
			maxQty = prd.getQuantity()-prd.getQuantityReported();
			sdc = prd.getSdc();
			dpaCost = prd.getApprovedPrice();
			//customer
			customer.setName(dpa.getCustomer().getName());
			customer.setLocation(dpa.getCustomer().getLocation());
			customer.setAccountancyId(dpa.getCustomer().getAccountancyId());
			customer.setState(dpa.getCustomer().getState());
			customer.setCountry(dpa.getCustomer().getCountry());
			customer.setZipCode(dpa.getCustomer().getZipCode());
			customer.setId(dpa.getCustomer().getId());
			
			//proud
			product.setDialogicItemKey(prd.getProduct().getDialogicItemKey());
			product.setId(prd.getProduct().getId());
			product.setProductName(prd.getProduct().getProductName());
			dpaProdId = prd.getId();
		}			
		
	}
	/**
	 * This method is called by the JSF when the users adds a product from a dpa
	 * into the pos products lists. it updates the quantity in the tables.
	 * 
	 */
	public void putProdIntoPosWithDpa(){
		PosProductDO posProductDO = new PosProductDO();
		DpaProductDO prd =prodMap.get(selectedProdFormTable);
		
		posProductDO.setCustomer(customer.cloneCustomer());
		posProductDO.setProduct(prd.getProduct().cloneProduct());
		
		
		//pos data
		posProductDO.setInvoiceLine(distiLine);
		posProductDO.setInvoiceNumber(distiInvoice);
		posProductDO.setDpaId(dpaId);
		posProductDO.setSdc(sdc);
		posProductDO.setDpaCost(dpaCost);
		posProductDO.setQuantity(qty);
		posProductDO.setResalePrice(distributorResalePrice);
		posProductDO.setShipDate(shipDate);
		posProductDO.setCurrency(transCurr);
		//creating link to the dpa proudct
		DpaProductDO d = new DpaProductDO();
		d.setId(dpaProdId);
		posProductDO.setDpaProduct(d);
		posProductList.add(posProductDO);
		prd.setQuantityReported(prd.getQuantityReported()+qty);
		cleanAllFields();
	}
	/**
	 * This method is called by the JSF when the users adds a product not from a dpa
	 * into the pos products lists.
	 * 
	 */
	public void putProdIntoPosWithoutDpa(){
		PosProductDO posProductDO = new PosProductDO();
		
		posProductDO.setCustomer(customerN.cloneCustomer());
		
		posProductDO.setProduct(productN.cloneProduct());
		

		
		//pos data
		posProductDO.setInvoiceLine(distiLineN);
		posProductDO.setInvoiceNumber(distiInvoiceN);
		posProductDO.setDpaId(null);
		posProductDO.setSdc(sdcN);
		posProductDO.setDpaCost(0);
		posProductDO.setQuantity(qtyN);
		posProductDO.setResalePrice(distributorResalePriceN);
		posProductDO.setShipDate(shipDateN);
		posProductDO.setCurrency(transCurrN);
		//pos.
		posProductList.add(posProductDO);
		//check if the product comes form a dpa
		cleanAllFields();
	}
	/**
	 * This method clears all the products fields
	 * 
	 */
	private void cleanAllFields() {

		selectedProdFormTable=0;
		//Fields for the dpa panel
		customer= new CustomerDO();
		userCountry= null;
		distiInvoice=0;
		distiLine=0;
		product = new ProductDO();
		dpaId=null;
		sdc=0;
		dpaCost=0;
		qty=0;
		maxQty=0;
		transCurr =null;
		distributorResalePrice=0;
		shipDate=null;
		
		//Fields for the not dpa panel
		customerN=new CustomerDO();
		userCountryN=null;
		distiInvoiceN=0;
		distiLineN=0;
		productN= new ProductDO();
		sdcN=0;
		qtyN=0;
		transCurrN =null;
		distributorResalePriceN=0;
		shipDateN=null;
	}
	/**
	 * This method is called when a products is removed. if this product reported in a DPA
	 * it's quantity returns to the table
	 * 
	 * 
	 */
	public void removePrd(){
		PosProductDO prd = posProductList.get(removePrdIdx);
		//if the product came form the a dpa then we need to update the qty
		if (prd.getDpaId()!=null){
			for (DpaDO dpa : dpaList) {
				for (DpaProductDO dpaprd : dpa.getDpaProducts()) {
					if (dpa.getDpaId().equals(prd.getDpaId()) && 
							dpaprd.getProduct().getDialogicItemKey().equals(prd.getProduct().getDialogicItemKey())){
						dpaprd.setQuantityReported(dpaprd.getQuantityReported()-prd.getQuantity());
						
					}
				}
			}	
		}
		
		posProductList.remove(removePrdIdx);
		if (prd.getId()!=0)
			removePrds.add(prd);
		
	}
	/**
	 * 
	 * This method is called by JSF when the user wants to save the POS request
	 * 
	 * @return a paged to be directed to
	 */
	public String createRequest(){
		
		logger.debug("create new POS request");
		try {
			facade.createNewPOSRequest( buildPOSDo());
			
		}catch (MZRInternalServerException e) {
			logger.error(e.getMessage(), e);
			return "opr/failedopr.jsp";
		} catch (MZRApplicativeException e) {
			logger.error(e.getMessage(), e);
			return "opr/failedopr.jsp";
		}
		removeOldPrds();
		return "opr/successnewfilereq.jsp";
	}
	/**
	 * This method is called when the user chose to remove proudest form the dpa draft
	 * is removes those products form the system
	 * 
	 * 
	 */
	private void removeOldPrds() {
		if (removePrds.size()!=0){
			logger.debug("deleting old produtcs");
			try {
				facade.removePOSProducts( removePrds);
				
			}catch (MZRInternalServerException e) {
				logger.error(e.getMessage(), e);
			}
		}
		
	}
	/**
	 * 
	 * This method builds a POS DO from the data in the bean. ready to be
	 * saved in the system
	 * 
	 * @return PosDO
	 */
	private PosDO buildPOSDo() {
		PosDO pos = new PosDO();
		pos.setDate(Calendar.getInstance().getTime());
		pos.setEmail(email);
		pos.setId(posId);
		if (!cc.equals(""))
			pos.setCc(cc);
		else
			pos.setCc(null);
		pos.setPosProducts(posProductList);
		pos.updateFileName();
		return pos;
	}
	/**
	 * 
	 * This method is called by JSF when the user wants to save the POS request as draft
	 * 
	 * @return a paged to be directed to
	 */
	public String createDraft(){
		
		logger.debug("saving POS as draft");
		try {
			facade.savePOSDraft( buildPOSDo());
			
		}catch (MZRInternalServerException e) {
			logger.error(e.getMessage(), e);
			return "opr/failedopr.jsp";
		} 
		removeOldPrds();
		return "opr/successdraft.jsp";
	}
	/**
	 * This method is called when the user wants to fill the page with data from a draft
	 * it has selected
	 * 
	 */
	
	public  void loadDraft(){
		//find selected draft
		PosDO draft =null;
		for (PosDO d : drafts) {
			//TODO : change according to the file name
			if (selectedDraft.equals(String.valueOf(d.getFileName())))
				draft=d;
		}
		posId= draft.getId();
		email = draft.getEmail();
		cc = draft.getCc();
		posProductList = draft.getPosProducts();
		//updating the quantity of the dpa products
		for (PosProductDO draftedPrd : posProductList) {
			if (draftedPrd.getDpaId() !=null && draftedPrd.getDpaProduct() !=null){
				DpaDO cachedDpa = dpaMap.get(draftedPrd.getDpaId());
				for (DpaProductDO prd : cachedDpa.getDpaProducts()) {
					if (prd.getId()==draftedPrd.getDpaProduct().getId()){
						prd.setQuantityReported(prd.getQuantityReported()+draftedPrd.getQuantity());
					}	
				}
			}
		}
	}
	
	public void setEmail(String email) {
		this.email = email;
	}

	public String getEmail() {
		return email;
	}

	public CustomerDO getCustomer() {
		return customer;
	}

	public void setCustomer(CustomerDO customer) {
		this.customer = customer;
	}

	public String getUserCountry() {
		return userCountry;
	}

	public void setUserCountry(String userCountry) {
		this.userCountry = userCountry;
	}

	public int getDistiInvoice() {
		return distiInvoice;
	}

	public void setDistiInvoice(int distiInvoice) {
		this.distiInvoice = distiInvoice;
	}

	public ProductDO getProduct() {
		return product;
	}

	public void setProduct(ProductDO product) {
		this.product = product;
	}

	public int getDistiLine() {
		return distiLine;
	}

	public void setDistiLine(int distiLine) {
		this.distiLine = distiLine;
	}

	public String getDpaId() {
		return dpaId;
	}

	public void setDpaId(String dpaId) {
		this.dpaId = dpaId;
	}

	public double getSdc() {
		return sdc;
	}

	public void setSdc(double sdc) {
		this.sdc = sdc;
	}

	public double getDpaCost() {
		return dpaCost;
	}

	public void setDpaCost(double dpaCost) {
		this.dpaCost = dpaCost;
	}

	
	public int getMaxQty() {
		return maxQty;
	}

	public void setMaxQty(int maxQty) {
		this.maxQty = maxQty;
	}

	public int getQty() {
		return qty;
	}

	public void setQty(int qty) {
		this.qty = qty;
	}

	public String getTransCurr() {
		return transCurr;
	}

	public void setTransCurr(String transCurr) {
		this.transCurr = transCurr;
	}

	public double getDistributorResalePrice() {
		return distributorResalePrice;
	}

	public void setDistributorResalePrice(double distributorResalePrice) {
		this.distributorResalePrice = distributorResalePrice;
	}

	public Date getShipDate() {
		return shipDate;
	}

	public void setShipDate(Date shipDate) {
		this.shipDate = shipDate;
	}

	public void setCustomerN(CustomerDO customerN) {
		this.customerN = customerN;
	}

	public CustomerDO getCustomerN() {
		return customerN;
	}

	public void setUserCountryN(String userCountryN) {
		this.userCountryN = userCountryN;
	}

	public String getUserCountryN() {
		return userCountryN;
	}

	public void setDistiInvoiceN(int distiInvoiceN) {
		this.distiInvoiceN = distiInvoiceN;
	}

	public int getDistiInvoiceN() {
		return distiInvoiceN;
	}

	public void setDistiLineN(int distiLineN) {
		this.distiLineN = distiLineN;
	}

	public int getDistiLineN() {
		return distiLineN;
	}

	public void setProductN(ProductDO productN) {
		this.productN = productN;
	}

	public ProductDO getProductN() {
		return productN;
	}



	public void setSdcN(double sdcN) {
		this.sdcN = sdcN;
	}

	public double getSdcN() {
		return sdcN;
	}


	public void setQtyN(int qtyN) {
		this.qtyN = qtyN;
	}

	public int getQtyN() {
		return qtyN;
	}

	public void setTransCurrN(String transCurrN) {
		this.transCurrN = transCurrN;
	}

	public String getTransCurrN() {
		return transCurrN;
	}

	public void setDistributorResalePriceN(double distributorResalePriceN) {
		this.distributorResalePriceN = distributorResalePriceN;
	}

	public double getDistributorResalePriceN() {
		return distributorResalePriceN;
	}

	public void setShipDateN(Date shipDateN) {
		this.shipDateN = shipDateN;
	}

	public Date getShipDateN() {
		return shipDateN;
	}

	public void setRemovePrdIdx(int removePrdIdx) {
		this.removePrdIdx = removePrdIdx;
	}

	public int getRemovePrdIdx() {
		return removePrdIdx;
	}

	public void setCc(String cc) {
		this.cc = cc;
	}

	public String getCc() {
		return cc;
	}

	public String getSelectedDpaIdFormTable() {
		return selectedDpaIdFormTable;
	}

	public void setDpaMap(Map<String, DpaDO> dpaMap) {
		this.dpaMap = dpaMap;
	}

	public void setSelectedDpaIdFormTable(String id) {
		this.selectedDpaIdFormTable = id;
	}

	

	public List<DpaDO> getDpaList() {
		return dpaList;
	}

	public void setDpaList(List<DpaDO> dpaList) {
		this.dpaList = dpaList;
	}



	
	public List<DpaProductDO> getProductList() {
		return productList;
	}


	public void setProductList(List<DpaProductDO> productList) {
		this.productList = productList;
	}


	public Map<String, DpaDO> getDpaMap() {
		return dpaMap;
	}


	public void setDpaList(Map<String, DpaDO> dpaMap) {
		this.dpaMap = dpaMap;
	}

	public int getSelectedProdFormTable() {
		return selectedProdFormTable;
	}

	public void setSelectedProdFormTable(int selectedProdFormTable) {
		this.selectedProdFormTable = selectedProdFormTable;
	}
	

	public List<PosProductDO> getPosProductList() {
		return posProductList;
	}

	public void setPosProductList(List<PosProductDO> posProductList) {
		this.posProductList = posProductList;
	}

	public void setDrafts(List<PosDO> drafts) {
		this.drafts = drafts;
	}

	public List<PosDO> getDrafts() {
		return drafts;
	}

	public void setDraftsLabel(List<SelectItem > draftsLabel) {
		this.draftsLabel = draftsLabel;
	}

	public List<SelectItem > getDraftsLabel() {
		return draftsLabel;
	}

	public void setSelectedDraft(String selectedDraft) {
		this.selectedDraft = selectedDraft;
	}

	public String getSelectedDraft() {
		return selectedDraft;
	}

	
}
